package com.jeesite.modules.kj.api.wechatUtils;

import com.alibaba.fastjson.JSONObject;
import com.jeesite.common.cache.CacheUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.codec.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Map;

@Slf4j
public class WechatHelper {

    private static final Logger logger = LoggerFactory.getLogger(WechatHelper.class);
    // 网页授权接口
    public final static String GetPageAccessTokenUrl = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=CODE&grant_type=authorization_code";
    public final static String URL_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$APPID&secret=$APPSECRET";
    public final static String URL_CODE = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=$ACCESS_TOKEN";
    public final static String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=$ACCESS_TOKEN";


    public static JSONObject oauth2GetOpenid(String appid, String code, String appsecret) {
        String requestUrl = GetPageAccessTokenUrl.replace("APPID", appid).replace("SECRET", appsecret).replace("CODE", code);
        HttpClient client = null;
        JSONObject result = new JSONObject();
        try {
            client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(requestUrl);
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            String response = client.execute(httpget, responseHandler);
//            logger.info("获取小程序OpendID：" + response);
            JSONObject OpenidJSONO = JSONObject.parseObject(response);
            String openid = String.valueOf(OpenidJSONO.get("openid"));
            String session_key = String.valueOf(OpenidJSONO.get("session_key"));
            String unionid = String.valueOf(OpenidJSONO.get("unionid"));
            String errcode = String.valueOf(OpenidJSONO.get("errcode"));
            String errmsg = String.valueOf(OpenidJSONO.get("errmsg"));

            result.put("openid", openid);
            result.put("sessionKey", session_key);
            result.put("unionid", unionid);
            result.put("errcode", errcode);
            result.put("errmsg", errmsg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            client.getConnectionManager().shutdown();
        }
        return result;
    }

    /**
     获取token
     */
    public static String getAccessTokenCache(String appid, String appsecret) throws Exception {

        //替换获取token链接中AppID和Secret

        Object access_token = CacheUtils.get("tokenTable","token");

        if (access_token != null) {
            JSONObject jsonObject = (JSONObject) access_token;
            long startTime = jsonObject.getLongValue("startTime");
            long l = System.currentTimeMillis();
            if (l-startTime<=7200000){
                return jsonObject.getString("access_token");
            }
        }
        String requestUrl = URL_TOKEN.replace("$APPID", appid).replace("$APPSECRET", appsecret);

        //创建http连接客户端

        CloseableHttpClient client = HttpClients.createDefault();

        //使用HTTPGet方法访问获取token链接url

        HttpGet method = new HttpGet(requestUrl);

        //执行HttpGet方法

        HttpResponse response = client.execute(method);

        //返回对象最后处理成jsonObject

        logger.info("微信获取微信小程序token                               向微信服务器发起get请求:" + requestUrl);
        HttpEntity httpEntity = response.getEntity();
        if (null == httpEntity) {
            logger.error("微信获取微信token 和微信通信返回值为null");
            throw new Exception("服务器异常");
        }
        String jsonString = "";
        try {
            jsonString = EntityUtils.toString(httpEntity);
        } catch (IOException e) {
            logger.error("微信获取微信小程序token 返回值转换字符串是不", e);
            throw new Exception("服务器异常");
        }
        JSONObject result = JSONObject.parseObject(jsonString);
        if (null == result) {
            logger.error("微信获取微信小程序token 返回值不是json字符串");
            throw new Exception("服务器异常");
        }
        if (null != result.get("errcode") && result.getInteger("errcode") > 0) {
            logger.error("微信获取微信小程序token 微信服务器返回错误:" + jsonString);
            throw new Exception("服务器异常");
        }
        logger.info("微信获取微信小程序token " + result);
        String access_token1 = result.getString("access_token");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("access_token",access_token1);
        jsonObject.put("startTime", System.currentTimeMillis());
        CacheUtils.put("tokenTable","token",jsonObject);
        return access_token1;

    }
    /**

     url:传入带token的获取二维码url链接

     map：获取post参数

     */
    public static byte[] doImgPost(String url, Map<String, Object> map) {

        byte[] result = null;

        //使用HTTPPost方法访问获取二维码链接url

        HttpPost httpPost = new HttpPost(url);

        //创建http连接客户端

        CloseableHttpClient client = HttpClients.createDefault();

        //设置头响应类型

        httpPost.addHeader("Content-Type", "application/json");
        try {
            // 设置请求的参数
            JSONObject postData = new JSONObject();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                postData.put(entry.getKey(), entry.getValue());
            }
            httpPost.setEntity(new StringEntity(postData.toString(), "UTF-8"));

            logger.info("微信获取微信二维码post数据 " + postData.toString());

            //返回的post请求结果

            HttpResponse response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toByteArray(entity);
        } catch (ConnectionPoolTimeoutException e) {
            logger.error("http get throw ConnectionPoolTimeoutException(wait time out)", e);
        } catch (ConnectTimeoutException e) {
            logger.error("http get throw ConnectTimeoutException", e);
        } catch (SocketTimeoutException e) {
            logger.error("http get throw SocketTimeoutException", e);
        } catch (Exception e) {
            logger.error("http get throw Exception", e);
        } finally {
            httpPost.releaseConnection();

        }

        //最后转成2进制图片流

        return result;

    }


    public static String decrypt(String keyStr, String ivStr, String encDataStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {

        byte[] encData = Base64.decode(encDataStr);
        byte[] iv = Base64.decode(ivStr);
        byte[] key = Base64.decode(keyStr);

        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

        return new String(cipher.doFinal(encData),"UTF-8");
    }
}
